widget: Add :focus-on-click property
authorFlorian Müllner <fmuellner@gnome.org>
Fri, 23 Oct 2015 16:07:41 +0000 (18:07 +0200)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 3 Nov 2015 12:44:17 +0000 (07:44 -0500)
There are currently three widget that implement such a property, and
there are other widgets for which the behavior can make sense. It
seems like a good time to add the property to GtkWidget itself so
subclasses can choose to respect it without adding their own property.

https://bugzilla.gnome.org/show_bug.cgi?id=757269

gtk/gtkwidget.c
gtk/gtkwidget.h
gtk/gtkwidgetprivate.h

index fd53f5876c7c1aa355849088784a4e5b60141586..42bf421cee2a259c41c58840ae77afcf62888c12 100644 (file)
@@ -575,6 +575,7 @@ enum {
   PROP_CAN_FOCUS,
   PROP_HAS_FOCUS,
   PROP_IS_FOCUS,
+  PROP_FOCUS_ON_CLICK,
   PROP_CAN_DEFAULT,
   PROP_HAS_DEFAULT,
   PROP_RECEIVES_DEFAULT,
@@ -1196,6 +1197,25 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                             FALSE,
                             GTK_PARAM_READWRITE);
 
+  /**
+   * GtkWidget:focus-on-click:
+   *
+   * Whether the widget should grab focus when it is clicked with the mouse.
+   *
+   * This property is only relevant for widgets that can take focus.
+   *
+   * Before 3.20, several widgets (GtkButton, GtkFileChooserButton,
+   * GtkComboBox) implemented this property individually.
+   *
+   * Since: 3.20
+   */
+  widget_props[PROP_FOCUS_ON_CLICK] =
+      g_param_spec_boolean ("focus-on-click",
+                            P_("Focus on click"),
+                            P_("Whether the widget should grab focus when it is clicked with the mouse"),
+                            TRUE,
+                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
   widget_props[PROP_CAN_DEFAULT] =
       g_param_spec_boolean ("can-default",
                             P_("Can default"),
@@ -3695,6 +3715,9 @@ gtk_widget_set_property (GObject         *object,
       if (g_value_get_boolean (value))
        gtk_widget_grab_focus (widget);
       break;
+    case PROP_FOCUS_ON_CLICK:
+      gtk_widget_set_focus_on_click (widget, g_value_get_boolean (value));
+      break;
     case PROP_CAN_DEFAULT:
       gtk_widget_set_can_default (widget, g_value_get_boolean (value));
       break;
@@ -3885,6 +3908,9 @@ gtk_widget_get_property (GObject         *object,
     case PROP_IS_FOCUS:
       g_value_set_boolean (value, gtk_widget_is_focus (widget));
       break;
+    case PROP_FOCUS_ON_CLICK:
+      g_value_set_boolean (value, gtk_widget_get_focus_on_click (widget));
+      break;
     case PROP_CAN_DEFAULT:
       g_value_set_boolean (value, gtk_widget_get_can_default (widget));
       break;
@@ -4329,7 +4355,8 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
   priv->redraw_on_alloc = TRUE;
   priv->alloc_needed = TRUE;
   priv->alloc_needed_on_child = TRUE;
+  priv->focus_on_click = TRUE;
+
   switch (_gtk_widget_get_direction (widget))
     {
     case GTK_TEXT_DIR_LTR:
@@ -8448,6 +8475,59 @@ gtk_widget_is_focus (GtkWidget *widget)
     return FALSE;
 }
 
+/**
+ * gtk_widget_set_focus_on_click:
+ * @widget: a #GtkWidget
+ * @focus_on_click: whether the widget should grab focus when clicked with the mouse
+ *
+ * Sets whether the widget should grab focus when it is clicked with the mouse.
+ * Making mouse clicks not grab focus is useful in places like toolbars where
+ * you don’t want the keyboard focus removed from the main area of the
+ * application.
+ *
+ * Since: 3.20
+ **/
+void
+gtk_widget_set_focus_on_click (GtkWidget *widget,
+                              gboolean   focus_on_click)
+{
+  GtkWidgetPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  priv = widget->priv;
+
+  focus_on_click = focus_on_click != FALSE;
+
+  if (priv->focus_on_click != focus_on_click)
+    {
+      priv->focus_on_click = focus_on_click;
+
+      g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_FOCUS_ON_CLICK]);
+    }
+}
+
+/**
+ * gtk_widget_get_focus_on_click:
+ * @widget: a #GtkWidget
+ *
+ * Returns whether the widget should grab focus when it is clicked with the mouse.
+ * See gtk_widget_set_focus_on_click().
+ *
+ * Returns: %TRUE if the widget should grab focus when it is clicked with
+ *               the mouse.
+ *
+ * Since: 3.20
+ **/
+gboolean
+gtk_widget_get_focus_on_click (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return widget->priv->focus_on_click;
+}
+
+
 /**
  * gtk_widget_set_can_default:
  * @widget: a #GtkWidget
index 61881c2ed6d750defc0f2f365a4ead49a3845a1c..d428917062eb67be32faebd25b326f59c18189fc 100644 (file)
@@ -783,6 +783,11 @@ GDK_AVAILABLE_IN_3_2
 gboolean   gtk_widget_has_visible_focus   (GtkWidget           *widget);
 GDK_AVAILABLE_IN_ALL
 void       gtk_widget_grab_focus          (GtkWidget           *widget);
+GDK_AVAILABLE_IN_3_20
+void       gtk_widget_set_focus_on_click  (GtkWidget           *widget,
+                                           gboolean             focus_on_click);
+GDK_AVAILABLE_IN_3_20
+gboolean   gtk_widget_get_focus_on_click  (GtkWidget           *widget);
 
 GDK_AVAILABLE_IN_ALL
 void       gtk_widget_set_can_default     (GtkWidget           *widget,
index 484c1f38e10125f27735c4ead5881be8e3e79100..b1755969f96ab129b084a3a0e58a00e4be5ced5f 100644 (file)
@@ -56,6 +56,7 @@ struct _GtkWidgetPrivate
   guint sensitive             : 1;
   guint can_focus             : 1;
   guint has_focus             : 1;
+  guint focus_on_click        : 1;
   guint can_default           : 1;
   guint has_default           : 1;
   guint receives_default      : 1;